// MGCommandPage.h: interface for the CMGCommandPage class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_MGCOMMANDPAGE_H__880E504D_D219_4161_ACF1_4DE8F59378BE__INCLUDED_)
#define AFX_MGCOMMANDPAGE_H__880E504D_D219_4161_ACF1_4DE8F59378BE__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "resource.h"

#pragma warning(push)

#include <yvals.h>

#pragma warning(disable: 4018)

#include <vector>
#include <functional>

#pragma warning(pop)

class CMGCommandPage : 
	public CPropertyPageImpl<CMGCommandPage>
{
public:
	enum { IDD = IDD_MG_COMMAND };

	typedef CPropertyPageImpl<CMGCommandPage> baseClass;

	CMGCommandPage();
	virtual ~CMGCommandPage();

	BEGIN_MSG_MAP(CMGOptionsPage)
        MSG_WM_INITDIALOG(OnInitDialog)
		MESSAGE_HANDLER_EX(PSM_QUERYSIBLINGS, OnQuerySiblings)
		COMMAND_HANDLER_EX(IDC_ED_GESTURE_INPUT,			EN_CHANGE,			OnEnChangeEdGestureInput)
		COMMAND_HANDLER_EX(IDC_PB_LOAD_GESTURES,			BN_CLICKED,			OnBnClickedPbLoadGestures)
		COMMAND_HANDLER_EX(IDC_PB_SAVE_GESTURES,			BN_CLICKED,			OnBnClickedPbSaveGestures)
		COMMAND_HANDLER_EX(IDC_PB_ADD,						BN_CLICKED,			OnBnClickedPbAdd)
		COMMAND_HANDLER_EX(IDC_PB_REMOVE,					BN_CLICKED,			OnBnClickedPbRemove)
		COMMAND_HANDLER_EX(IDC_PB_UP,						BN_CLICKED,			OnBnClickedMouse)
		COMMAND_HANDLER_EX(IDC_PB_DOWN,						BN_CLICKED,			OnBnClickedMouse)
		COMMAND_HANDLER_EX(IDC_PB_LEFT,						BN_CLICKED,			OnBnClickedMouse)
		COMMAND_HANDLER_EX(IDC_PB_RIGHT,					BN_CLICKED,			OnBnClickedMouse)
		COMMAND_HANDLER_EX(IDC_PB_MIDDLE_BUTTON,			BN_CLICKED,			OnBnClickedMouse)
		COMMAND_HANDLER_EX(IDC_PB_RIGHT_BUTTON,				BN_CLICKED,			OnBnClickedMouse)
		COMMAND_HANDLER_EX(IDC_PB_LEFT_BUTTON,				BN_CLICKED,			OnBnClickedMouse)
		COMMAND_HANDLER_EX(IDC_PB_WHEEL_UP,					BN_CLICKED,			OnBnClickedWheel)
		COMMAND_HANDLER_EX(IDC_PB_WHEEL_DOWN,				BN_CLICKED,			OnBnClickedWheel)
		COMMAND_HANDLER_EX(IDC_PB_BACKSPACE,				BN_CLICKED,			OnBnClickedPbBackspace)
		COMMAND_HANDLER_EX(IDC_LB_COMMAND,					LBN_SELCHANGE,		OnSelChangeLbCommand)
		COMMAND_HANDLER_EX(IDC_CB_CATEGORY,					CBN_SELCHANGE,		OnSelChangeCbCategory)
		COMMAND_HANDLER_EX(IDC_CB_TARGET,					CBN_SELCHANGE,		OnSelChangeCbTarget)
		NOTIFY_HANDLER_EX(IDC_LC_REGISTERED_MOUSE_GESTURES,	LVN_ITEMCHANGED,	OnItemChangedLcRegisteredMouseGestures)
		NOTIFY_HANDLER_EX(IDC_LC_REGISTERED_MOUSE_GESTURES,	NM_KILLFOCUS ,		OnKillFocusLcRegisteredMouseGestures)
		NOTIFY_HANDLER_EX(IDC_LC_REGISTERED_MOUSE_GESTURES,	LVN_GETINFOTIP ,	OnGetInfoTipLcRegisteredMouseGestures)
		REFLECT_NOTIFICATIONS()
        CHAIN_MSG_MAP(baseClass)
	END_MSG_MAP()
		
	BOOL OnInitDialog (HWND hwndFocus, LPARAM lParam);
	LRESULT OnQuerySiblings(UINT uMsg, WPARAM wParam, LPARAM lParam);
	void OnEnChangeEdGestureInput(UINT uCode, int nID, HWND hwndCtrl);
	void OnBnClickedPbLoadGestures(UINT uCode, int nID, HWND hwndCtrl);
	void OnBnClickedPbSaveGestures(UINT uCode, int nID, HWND hwndCtrl);
	void OnBnClickedPbAdd(UINT uCode, int nID, HWND hwndCtrl);
	void OnBnClickedPbRemove(UINT uCode, int nID, HWND hwndCtrl);
	void OnBnClickedMouse(UINT uCode, int nID, HWND hwndCtrl);
	void OnBnClickedWheel(UINT uCode, int nID, HWND hwndCtrl);
	void OnBnClickedPbBackspace(UINT uCode, int nID, HWND hwndCtrl);
	void OnSelChangeLbCommand(UINT uCode, int nID, HWND hwndCtrl);
	void OnSelChangeCbCategory(UINT uCode, int nID, HWND hwndCtrl);
	void OnSelChangeCbTarget(UINT uCode, int nID, HWND hwndCtrl);
	LRESULT OnItemChangedLcRegisteredMouseGestures(LPNMHDR pNMHDR);
	LRESULT OnKillFocusLcRegisteredMouseGestures(LPNMHDR pNMHDR);
	LRESULT OnGetInfoTipLcRegisteredMouseGestures(LPNMHDR pNMHDR);
	
protected:
	void UpdateControls();
	void UpdateRegistredGestureList();
	void InitCommands();
	void EnumIEMenu();
	void EnumIEContextMenu();
	void AddContextMenu(HMENU hMenu, DWORD dwID);
	void DFSMenu(HMENU hMenu, int &rnDepth, LPCTSTR pszPrefix = NULL, BYTE bCatID = -1);
	void AddCommand(WORD wID, LPCTSTR pszID, BYTE bCatID);
	void AddCategory(BYTE bCatID, LPCTSTR pszCat);
	void InitTargets();
	int ReloadCommand(BYTE bCatID);
	void AddAdvanceMenu();

#ifndef _UNICODE

	// OLE2T converions helper (to avoid macro in loop)
	void LcRegisteredMouseGestureInsertItem(int iIndex);
	std::string GetCommandID(LPCSTR sMenuItem, BSTR sBuf);
	void CbTargetInsertString(int iIndex, BSTR sBuf);
	void AddAcvanceCommand(WORD wID, BSTR sID);

#endif	// #ifndef _UNICODE


protected:
	CComboBox			c_cbCategory;
	CComboBox			c_cbTarget;
	CListBox			c_lbCommand;

	CButton				c_pbWheelUp;
	CButton				c_pbWheelDown;
	CButton				c_pbUp;
	CButton				c_pbDown;
	CButton				c_pbRight;
	CButton				c_pbLeft;
	CButton				c_pbBackspace;

	CButton				c_pbRightButton;
	CButton				c_pbLeftButton;
	CButton				c_pbMiddleButton;

	CButton				c_pbAdd;
	CButton				c_pbRemove;

	CEdit				c_edGestureInput;

	CButton				c_pbLoadGestures;
	CButton				c_pbSaveGestures;

	CListViewCtrl		c_lcRegisteredMouseGesture;

private:
	static const unsigned int MAX_GESTURE_INPUT;

	BOOL m_bInitDialog;
	BOOL m_bWheelCommand;
	BOOL m_bMiddleButton;
	int m_nGestureSelected;
	static const CBDATA rgCategory[];
	static const CBDATA rgTarget[];

	typedef struct tagCOMMAND
	{
		WORD wID;
		LPTSTR pszID;
		BYTE bCatID;
	} COMMAND, * LPCOMMAND;

	struct COMMANDVECTOR : std::vector<LPCOMMAND>
	{
		// functor to delete the object from memory
		struct Delete_t
		{
			void operator() (LPCOMMAND pCommand)
			{
				delete [] pCommand->pszID;
				pCommand->pszID = NULL;
				delete pCommand;
				pCommand = NULL;
			}
		};
	} m_vlpCommand;

	static struct COMMANDCOMP : std::binary_function<int, int, bool>
	{
		COMMANDCOMP(const COMMANDVECTOR &vlpCommand) : m_rvlpCommand(vlpCommand) { }

		bool operator() (int a, int b) const
		{
			return (0 > ::lstrcmp(m_rvlpCommand.at(a)->pszID, m_rvlpCommand.at(b)->pszID));
		}

	private:
		const COMMANDVECTOR &m_rvlpCommand;
	};
};

#endif // !defined(AFX_MGCOMMANDPAGE_H__880E504D_D219_4161_ACF1_4DE8F59378BE__INCLUDED_)
